home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / zm16src / zm.c < prev    next >
C/C++ Source or Header  |  1988-05-18  |  14KB  |  700 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *        Jwahar Bammi
  12.  *            usenet: mandrill!bammi@{decvax,sun}.UUCP
  13.  *            csnet:  bammi@mandrill.ces.CWRU.edu
  14.  *            arpa:   bammi@mandrill.ces.CWRU.edu
  15.  *            CompuServe: 71515,155
  16.  */
  17.  
  18. /*
  19.  *   Z M . C
  20.  *    ZMODEM protocol primitives
  21.  *    01-15-87  Chuck Forsberg Omen Technology Inc
  22.  *
  23.  * Entry point Functions:
  24.  *    zsbhdr(type, hdr) send binary header
  25.  *    zshhdr(type, hdr) send hex header
  26.  *    zgethdr(hdr, eflag) receive header - binary or hex
  27.  *    zsdata(buf, len, frameend) send data
  28.  *    zrdata(buf, len) receive data
  29.  *    stohdr(pos) store position data in Txhdr
  30.  *    long rclhdr(hdr) recover position offset from header
  31.  */
  32. #include "config.h"
  33. #include "zmdm.h"
  34. #include "common.h"
  35.  
  36. #ifndef CANFDX
  37. #include "zmodem.h"
  38. #endif
  39.  
  40. #define xsendline(X) sendline(X)
  41.  
  42. static char *frametypes[] = {
  43.     "Carrier Lost",        /* -3 */
  44.     "TIMEOUT",        /* -2 */
  45.     "ERROR",        /* -1 */
  46. #define FTOFFSET 3
  47.     "ZRQINIT",
  48.     "ZRINIT",
  49.     "ZSINIT",
  50.     "ZACK",
  51.     "ZFILE",
  52.     "ZSKIP",
  53.     "ZNAK",
  54.     "ZABORT",
  55.     "ZFIN",
  56.     "ZRPOS",
  57.     "ZDATA",
  58.     "ZEOF",
  59.     "ZFERR",
  60.     "ZCRC",
  61.     "ZCHALLENGE",
  62.     "ZCOMPL",
  63.     "ZCAN",
  64.     "ZFREECNT",
  65.     "ZCOMMAND",
  66.     "ZSTDERR",
  67.     "xxxxx"
  68. #define FRTYPES 22    /* Total number of frame types in this array */
  69.             /*  not including psuedo negative entries */
  70. };
  71.  
  72. /* Send ZMODEM binary header hdr of type type */
  73. zsbhdr(type, hdr)
  74. register int type;
  75. register char *hdr;
  76. {
  77.     register int n;
  78.     register unsigned int crc;
  79.  
  80.     vfile2("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  81.     if (type == ZDATA)
  82.         for (n = Znulls; --n >=0; )
  83.             zsendline(0);
  84.  
  85.     xsendline(ZPAD); xsendline(ZDLE);
  86.  
  87.     if (Txfcs32)
  88.         zsbh32(hdr, type);
  89.     else {
  90.         xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
  91.  
  92.         for (n=4; --n >= 0;) {
  93.             zsendline(*hdr);
  94.             crc = updcrc((0377& *hdr++), crc);
  95.         }
  96.         crc = updcrc(0,updcrc(0,crc));
  97.         zsendline(crc>>8);
  98.         zsendline(crc);
  99.     }
  100.     if (type != ZDATA)
  101.         flush_modem();
  102. }
  103.  
  104.  
  105. /* Send ZMODEM binary header hdr of type type */
  106. zsbh32(hdr, type)
  107. register char *hdr;
  108. register int type;
  109. {
  110.     register int n;
  111.     register unsigned long crc;
  112.  
  113.     xsendline(ZBIN32);  zsendline(type);
  114.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  115.  
  116.     for (n=4; --n >= 0;) {
  117.         zsendline(*hdr);
  118.         crc = UPDC32((0377& *hdr++), crc);
  119.     }
  120.     crc = ~crc;
  121.     for (n=4; --n >= 0;) {
  122.         zsendline((unsigned int)(crc&0xFFFF));  crc >>= 8;
  123.     }
  124. }
  125.  
  126. /* Send ZMODEM HEX header hdr of type type */
  127. zshhdr(type, hdr)
  128. register int type;
  129. register char *hdr;
  130. {
  131.     register int n;
  132.     register unsigned int crc;
  133.  
  134.     vfile2("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  135.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  136.     zputhex(type);
  137.  
  138.     crc = updcrc(type, 0);
  139.     for (n=4; --n >= 0;) {
  140.         zputhex(*hdr); crc = updcrc((0377& *hdr++), crc);
  141.     }
  142.     crc = updcrc(0,updcrc(0,crc));
  143.     zputhex(crc>>8); zputhex(crc);
  144.  
  145.     /* Make it printable on remote machine */
  146.     sendline(015); sendline(012);
  147.     /*
  148.      * Uncork the remote in case a fake XOFF has stopped data flow
  149.      */
  150.     if (type != ZFIN)
  151.         sendline(021);
  152.     flush_modem();
  153. }
  154.  
  155. /*
  156.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  157.  */
  158. zsdata(buf, length, frameend)
  159. register char *buf;
  160. register int length, frameend;
  161. {
  162.     register unsigned int crc;
  163.  
  164.     vfile("zsdata: length=%d end=%x", length, frameend);
  165.     if (Txfcs32)
  166.         zsda32(buf, length, frameend);
  167.     else {
  168.         crc = 0;
  169.         for (;--length >= 0;) {
  170.             zsendline(*buf);
  171.             crc = updcrc((0377& *buf++), crc);
  172.         }
  173.         xsendline(ZDLE); xsendline(frameend);
  174.         crc = updcrc(frameend, crc);
  175.  
  176.         crc = updcrc(0,updcrc(0,crc));
  177.         zsendline(crc>>8); zsendline(crc);
  178.     }
  179.     if (frameend == ZCRCW) {
  180.         xsendline(XON);   flush_modem();
  181.     }
  182. }
  183.  
  184. zsda32(buf, length, frameend)
  185. register char *buf;
  186. register int length, frameend;
  187. {
  188.     register unsigned long crc;
  189.  
  190.     crc = 0xFFFFFFFFL;
  191.     for (;--length >= 0;) {
  192.         zsendline(*buf); crc = UPDC32((0377& *buf++), crc);
  193.     }
  194.     xsendline(ZDLE); xsendline(frameend);
  195.     crc = UPDC32(frameend, crc);
  196.  
  197.     crc = ~crc;
  198.     for (length=4; --length >= 0;) {
  199.         zsendline((unsigned int)(crc&0xFFFF));  crc >>= 8;
  200.     }
  201. }
  202.  
  203. /*
  204.  * Receive array buf of max length with ending ZDLE sequence
  205.  *  and CRC.  Returns the ending character or error code.
  206.  */
  207. zrdata(buf, length)
  208. register char *buf;
  209. register int length;
  210. {
  211.     register int c;
  212.     register unsigned int crc;
  213.     register int d;
  214.  
  215.     if (Rxframeind == ZBIN32)
  216.         return zrdat32(buf, length);
  217.  
  218.     crc = Rxcount = 0;
  219.     for (;;) {
  220.         if ((c = zdlread()) & ~0377) {
  221. crcfoo:
  222.             switch (c) {
  223.             case GOTCRCE:
  224.             case GOTCRCG:
  225.             case GOTCRCQ:
  226.             case GOTCRCW:
  227.                 crc = updcrc((d=c)&0377, crc);
  228.                 if ((c = zdlread()) & ~0377)
  229.                     goto crcfoo;
  230.                 crc = updcrc(c, crc);
  231.                 if ((c = zdlread()) & ~0377)
  232.                     goto crcfoo;
  233.                 crc = updcrc(c, crc);
  234.                 if (crc & 0xFFFF) {
  235.                     log2("Bad data CRC %x", crc);
  236.                     return ERROR;
  237.                 }
  238.                 vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
  239.                 return d;
  240.             case GOTCAN:
  241.                 log2("ZMODEM: Sender Canceled");
  242.                 return ZCAN;
  243.             case TIMEOUT:
  244.                 log2("ZMODEM data TIMEOUT");
  245.                 return c;
  246.             default:
  247.                 log2("ZMODEM bad data subpacket ret=%x", c);
  248.                 return c;
  249.             }
  250.         }
  251.         if (--length < 0) {
  252.             log2("ZMODEM data subpacket too long");
  253.             return ERROR;
  254.         }
  255.         ++Rxcount;
  256.         *buf++ = c;
  257.         crc = updcrc(c, crc);
  258.         continue;
  259.     }
  260. }
  261. zrdat32(buf, length)
  262. register char *buf;
  263. register int length;
  264. {
  265.     register int c;
  266.     register unsigned long crc;
  267.     register int d;
  268.  
  269.     crc = 0xFFFFFFFFL;  Rxcount = 0;
  270.     for (;;) {
  271.         if ((c = zdlread()) & ~0377) {
  272. crcfoo:
  273.             switch (c) {
  274.             case GOTCRCE:
  275.             case GOTCRCG:
  276.             case GOTCRCQ:
  277.             case GOTCRCW:
  278.                 crc = UPDC32((d=c)&0377, crc);
  279.                 if ((c = zdlread()) & ~0377)
  280.                     goto crcfoo;
  281.                 crc = UPDC32(c, crc);
  282.                 if ((c = zdlread()) & ~0377)
  283.                     goto crcfoo;
  284.                 crc = UPDC32(c, crc);
  285.                 if ((c = zdlread()) & ~0377)
  286.                     goto crcfoo;
  287.                 crc = UPDC32(c, crc);
  288.                 if ((c = zdlread()) & ~0377)
  289.                     goto crcfoo;
  290.                 crc = UPDC32(c, crc);
  291.                 if (crc != 0xDEBB20E3L) {
  292.                     log2("Bad data CRC");
  293.                     return ERROR;
  294.                 }
  295.                 vfile2("zrdat32: cnt = %ld ret = %x", Rxcount, d);
  296.                 return d;
  297.             case GOTCAN:
  298.                 log2("ZMODEM: Sender Canceled");
  299.                 return ZCAN;
  300.             case TIMEOUT:
  301.                 log2("ZMODEM data TIMEOUT");
  302.                 return c;
  303.             default:
  304.                 log2("ZMODEM bad data subpacket ret");
  305.                 return c;
  306.             }
  307.         }
  308.         if (--length < 0) {
  309.             log2("ZMODEM data subpacket too long");
  310.             return ERROR;
  311.         }
  312.         ++Rxcount;
  313.         *buf++ = c;
  314.         crc = UPDC32(c, crc);
  315.         continue;
  316.     }
  317. }
  318.  
  319.  
  320. /*
  321.  * Read a ZMODEM header to hdr, either binary or hex.
  322.  *  eflag controls local display of non zmodem characters:
  323.  *    0:  no display
  324.  *    1:  display printing characters only
  325.  *    2:  display all non ZMODEM characters
  326.  *  On success, set Zmodem to 1 and return type of header.
  327.  *   Otherwise return negative on error
  328.  */
  329. zgethdr(hdr, eflag)
  330. register char *hdr;
  331. register int eflag;
  332. {
  333.     register int c, n, cancount;
  334.  
  335.     n = Baudrate;    /* Max characters before start of frame */
  336.     cancount = 5;
  337. again:
  338.     Rxframeind = Rxtype = 0;
  339.     switch (c = noxread7()) {
  340.     case RCDO:
  341.     case TIMEOUT:
  342.         goto fifi;
  343.     case CAN:
  344.         if (--cancount <= 0) {
  345.             c = ZCAN; goto fifi;
  346.         }
  347.     /* **** FALL THRU TO **** */
  348.     default:
  349. agn2:
  350.         if ( --n == 0) {
  351.             log2("ZMODEM Garbage count exceeded");
  352.             return(ERROR);
  353.         }
  354.         if (eflag && ((c &= 0177) & 0140))
  355.             bttyout(c);
  356.         else if (eflag > 1)
  357.             bttyout(c);
  358.         if (c != CAN)
  359.             cancount = 5;
  360.         goto again;
  361.     case ZPAD:        /* This is what we want. */
  362.         break;
  363.     }
  364.     cancount = 5;
  365. splat:
  366.     switch (c = noxread7()) {
  367.     case ZPAD:
  368.         goto splat;
  369.     case RCDO:
  370.     case TIMEOUT:
  371.         goto fifi;
  372.     default:
  373.         goto agn2;
  374.     case ZDLE:        /* This is what we want. */
  375.         break;
  376.     }
  377.  
  378.     switch (c = noxread7()) {
  379.     case RCDO:
  380.     case TIMEOUT:
  381.         goto fifi;
  382.     case ZBIN:
  383.         Rxframeind = ZBIN;
  384.         c =  zrbhdr(hdr);
  385.         break;
  386.     case ZBIN32:
  387.         Rxframeind = ZBIN32;
  388.         c =  zrbhdr32(hdr);
  389.         break;
  390.     case ZHEX:
  391.         Rxframeind = ZHEX;
  392.         c =  zrhhdr(hdr);
  393.         break;
  394.     case CAN:
  395.         if (--cancount <= 0) {
  396.             c = ZCAN; goto fifi;
  397.         }
  398.         goto agn2;
  399.     default:
  400.         goto agn2;
  401.     }
  402.     Rxpos = hdr[ZP3] & 0377;
  403.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  404.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  405.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  406. fifi:
  407.     switch (c) {
  408.     case GOTCAN:
  409.         c = ZCAN;
  410.     /* **** FALL THRU TO **** */
  411.     case ZNAK:
  412.     case ZCAN:
  413.     case ERROR:
  414.     case TIMEOUT:
  415.     case RCDO:
  416.         vfile2("ZMODEM: Got %s %s", frametypes[c+FTOFFSET],
  417.           (c >= 0) ? "header" : "error");
  418.     /* **** FALL THRU TO **** */
  419.     default:
  420.         if (c >= -3 && c <= FRTYPES)
  421.             vfile2("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
  422.         else
  423.             vfile2("zgethdr: %ld %lx", (long)c, Rxpos);
  424.     }
  425.     return c;
  426. }
  427.  
  428. /* Receive a binary style header (type and position) */
  429. zrbhdr(hdr)
  430. register char *hdr;
  431. {
  432.     register int c, n;
  433.     register unsigned int crc;
  434.  
  435.     if ((c = zdlread()) & ~0377)
  436.         return c;
  437.     Rxtype = c;
  438.     crc = updcrc(c, 0);
  439.  
  440.     for (n=4; --n >= 0;) {
  441.         if ((c = zdlread()) & ~0377)
  442.             return c;
  443.         crc = updcrc(c, crc);
  444.         *hdr++ = c;
  445.     }
  446.     if ((c = zdlread()) & ~0377)
  447.         return c;
  448.     crc = updcrc(c, crc);
  449.     if ((c = zdlread()) & ~0377)
  450.         return c;
  451.     crc = updcrc(c, crc);
  452.     if (crc & 0xFFFF) {
  453.         log2("Bad Header CRC"); return ERROR;
  454.     }
  455.     Zmodem = 1;
  456.     return Rxtype;
  457. }
  458.  
  459. /* Receive a binary style header (type and position) with 32 bit FCS */
  460. zrbhdr32(hdr)
  461. register char *hdr;
  462. {
  463.     register int c, n;
  464.     register unsigned long crc;
  465.  
  466.     if ((c = zdlread()) & ~0377)
  467.         return c;
  468.     Rxtype = c;
  469.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  470.  
  471.     for (n=4; --n >= 0;) {
  472.         if ((c = zdlread()) & ~0377)
  473.             return c;
  474.         crc = UPDC32(c, crc);
  475.         *hdr++ = c;
  476.     }
  477.     for (n=4; --n >= 0;) {
  478.         if ((c = zdlread()) & ~0377)
  479.             return c;
  480.         crc = UPDC32(c, crc);
  481.     }
  482.     if (crc != 0xDEBB20E3L) {
  483.         log2("Bad Header CRC"); return ERROR;
  484.     }
  485.     Zmodem = 1;
  486.     return Rxtype;
  487. }
  488.  
  489.  
  490. /* Receive a hex style header (type and position) */
  491. zrhhdr(hdr)
  492. char *hdr;
  493. {
  494.     register int c;
  495.     register unsigned int crc;
  496.     register int n;
  497.  
  498.     if ((c = zgethex()) < 0)
  499.         return c;
  500.     Rxtype = c;
  501.     crc = updcrc(c, 0);
  502.  
  503.     for (n=4; --n >= 0;) {
  504.         if ((c = zgethex()) < 0)
  505.             return c;
  506.         crc = updcrc(c, crc);
  507.         *hdr++ = c;
  508.     }
  509.     if ((c = zgethex()) < 0)
  510.         return c;
  511.     crc = updcrc(c, crc);
  512.     if ((c = zgethex()) < 0)
  513.         return c;
  514.     crc = updcrc(c, crc);
  515.     if (crc & 0xFFFF) {
  516.         log2("Bad Header CRC"); return ERROR;
  517.     }
  518.     if (readline(1) == '\r')    /* Throw away possible cr/lf */
  519.         readline(1);
  520.     Zmodem = 1; return Rxtype;
  521. }
  522.  
  523. /* Send a byte as two hex digits */
  524. zputhex(c)
  525. register int c;
  526. {
  527.     static char    digits[]    = "0123456789abcdef";
  528.  
  529.     if (Verbose>4)
  530.         vfile("zputhex: %x", c);
  531.     sendline(digits[(c&0xF0)>>4]);
  532.     sendline(digits[(c)&0xF]);
  533. }
  534.  
  535. /*
  536.  * Send character c with ZMODEM escape sequence encoding.
  537.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  538.  */
  539. zsendline(c)
  540. register int c;
  541. {
  542.     static int lastsent;
  543.  
  544.     switch (c & 0377) {
  545.     case ZDLE:
  546.         xsendline(ZDLE);
  547.         xsendline (lastsent = (c ^= 0100));
  548.         break;
  549.     case 015:
  550.     case 0215:
  551.         if ((lastsent & 0177) != '@')
  552.             goto sendit;
  553.     /* **** FALL THRU TO **** */
  554.     case 020:
  555.     case 021:
  556.     case 023:
  557.     case 0220:
  558.     case 0221:
  559.     case 0223:
  560.     if(SendType)
  561.     {
  562.         if (Zctlesc<0)
  563.             goto sendit;
  564.     }
  565.         
  566.         xsendline(ZDLE);
  567.         c ^= 0100;
  568. sendit:
  569.         xsendline(lastsent = c);
  570.         break;
  571.     default:
  572.         if(SendType)
  573.         {
  574.             if (Zctlesc>0 && ! (c & 0140)) {
  575.                 xsendline(ZDLE);
  576.                 c ^= 0100;
  577.             }
  578.         }
  579.         
  580.         xsendline(lastsent = c);
  581.     }
  582. }
  583.  
  584. /* Decode two lower case hex digits into an 8 bit byte value */
  585. zgethex()
  586. {
  587.     register int c;
  588.  
  589.     c = zgeth1();
  590.     if (Verbose>4)
  591.         vfile("zgethex: %x", c);
  592.     return c;
  593. }
  594. zgeth1()
  595. {
  596.     register int c, n;
  597.  
  598.     if ((c = noxread7()) < 0)
  599.         return c;
  600.     n = c - '0';
  601.     if (n > 9)
  602.         n -= ('a' - ':');
  603.     if (n & ~0xF)
  604.         return ERROR;
  605.     if ((c = noxread7()) < 0)
  606.         return c;
  607.     c -= '0';
  608.     if (c > 9)
  609.         c -= ('a' - ':');
  610.     if (c & ~0xF)
  611.         return ERROR;
  612.     c += (n<<4);
  613.     return c;
  614. }
  615.  
  616. /*
  617.  * Read a byte, checking for ZMODEM escape encoding
  618.  *  including CAN*5 which represents a quick abort
  619.  */
  620. zdlread()
  621. {
  622.     register int c;
  623.  
  624.     if ((c = readline(Rxtimeout)) != ZDLE)
  625.         return c;
  626.     if ((c = readline(Rxtimeout)) < 0)
  627.         return c;
  628.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  629.         return c;
  630.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  631.         return c;
  632.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  633.         return c;
  634.     switch (c) {
  635.     case CAN:
  636.         return GOTCAN;
  637.     case ZCRCE:
  638.     case ZCRCG:
  639.     case ZCRCQ:
  640.     case ZCRCW:
  641.         return (c | GOTOR);
  642.     case ZRUB0:
  643.         return 0177;
  644.     case ZRUB1:
  645.         return 0377;
  646.     default:
  647.         if ((c & 0140) ==  0100)
  648.             return (c ^ 0100);
  649.         break;
  650.     }
  651.     log2("Got bad ZMODEM escape sequence %x", c);
  652.     return ERROR;
  653. }
  654.  
  655. /*
  656.  * Read a character from the modem line with timeout.
  657.  *  Eat parity, XON and XOFF characters.
  658.  */
  659. noxread7()
  660. {
  661.     register int c;
  662.  
  663.     for (;;) {
  664.         if ((c = readline(Rxtimeout)) < 0)
  665.             return c;
  666.         switch (c &= 0177) {
  667.         case XON:
  668.         case XOFF:
  669.             continue;
  670.         default:
  671.             return c;
  672.         }
  673.     }
  674. }
  675.  
  676. /* Store long integer pos in Txhdr */
  677. stohdr(pos)
  678. register long pos;
  679. {
  680.     Txhdr[ZP0] = pos;
  681.     Txhdr[ZP1] = pos>>8;
  682.     Txhdr[ZP2] = pos>>16;
  683.     Txhdr[ZP3] = pos>>24;
  684. }
  685.  
  686. /* Recover a long integer from a header */
  687. long rclhdr(hdr)
  688. register char *hdr;
  689. {
  690.     register long l;
  691.  
  692.     l = (hdr[ZP3] & 0377);
  693.     l = (l << 8) | (hdr[ZP2] & 0377);
  694.     l = (l << 8) | (hdr[ZP1] & 0377);
  695.     l = (l << 8) | (hdr[ZP0] & 0377);
  696.     return l;
  697. }
  698.  
  699. /* -eof- */
  700.